import {
  DocumentObject,
  MenuItemDefinition,
  ObjectTreeMenuProps,
  ObjectTreeMenuUtils,
  sketchRootNodeTypes,
  Types,
} from '@amcax/base';
import { filterOutDescendants } from '@app-cad/common/events/CoreEvent';
import { ctx2, docMgr, userEvents } from '@app-cad/module';
import { ContextMenuEvents } from './events';
import { wsApi } from '@app-base/server';

export const MenuItemDelete: MenuItemDefinition<ObjectTreeMenuProps> = {
  id: 'delete',
  children: '删除',
  hidden: ({
    props: {
      documentObject: { type, dxid },
      selectedObjects,
    },
  }) => {
    const objects = filterOutDescendants(selectedObjects);

    if (objects.length > 1) {
      return objects.some((item) => {
        return (
          ObjectTreeMenuUtils.initialNodeTypes.includes(item?.type) ||
          sketchRootNodeTypes.includes(item?.type) ||
          item?.type === Types.MeasureResultRoot ||
          item?.dxid === docMgr.rootGeomBox?.dxid ||
          (item?.dxid && item?.dxid === docMgr.getCurrentSketchDxid()) ||
          item?.type === Types.PARAMETER_LINK
        );
      });
    }
    return (
      ObjectTreeMenuUtils.initialNodeTypes.includes(type) ||
      sketchRootNodeTypes.includes(type) ||
      type === Types.MeasureResultRoot ||
      dxid === docMgr.rootGeomBox?.dxid ||
      (dxid && dxid === docMgr.getCurrentSketchDxid())
    );
  },

  onClick: async ({ props: { documentObject, selectedObjects } }) => {
    const isDocumentsObjectArray = Array.isArray(selectedObjects);
    const hasOutlinks = (object: DocumentObject): boolean =>
      object?.outlinks?.length > 0 || object?.children?.some(hasOutlinks);

    const getAllOutlinks = (object: DocumentObject): Set<string> => {
      const outlinks = new Set(object?.recursiveOutlinks || []);
      object?.children?.forEach((child) =>
        getAllOutlinks(child).forEach(outlinks.add, outlinks),
      );
      return outlinks;
    };

    const recursiveOutlinks = isDocumentsObjectArray
      ? selectedObjects?.map((obj) => Array.from(getAllOutlinks(obj)))?.flat()
      : Array.from(getAllOutlinks(documentObject));

    const isSubsetArray = (subset: string[], parent: string[]) => {
      return subset.every((element) => parent.includes(element));
    };

    if (selectedObjects.length > 1) {
      // 多选情况暂时不支持Types.PARAMETER_LINK一并删除
      const objects = filterOutDescendants(selectedObjects);

      const deleteDxids = objects.map((item) => item?.dxid).filter(Boolean);
      if (selectedObjects.some((item) => hasOutlinks(item))) {
        const allOutlinks = Array.from(new Set(recursiveOutlinks));

        if (isSubsetArray(allOutlinks, deleteDxids)) {
          await ctx2.commandCenters.basicCommands.deleteObjects(deleteDxids);
        } else {
          userEvents.emit(ContextMenuEvents.ShowDeleteOutlinkDialog, objects);
        }
      } else {
        await ctx2.commandCenters.basicCommands.deleteObjects(deleteDxids);
      }
    } else {
      if (documentObject.type === Types.PARAMETER_LINK) {
        await wsApi.deleteParameterLink(documentObject.dxid);
        await docMgr.updateDocumentObjects();
      } else if (hasOutlinks(documentObject)) {
        userEvents.emit(ContextMenuEvents.ShowDeleteOutlinkDialog, [
          documentObject,
        ]);
      } else {
        await ctx2.commandCenters.basicCommands.deleteObjects([
          documentObject.dxid,
        ]);
      }
    }

    if (docMgr.workingObjectDxid === documentObject.dxid) {
      docMgr.workingObjectDxid = null;
    }
  },
};
